--[[
Copyright (C) 2006  Matt Richard

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
]]

SmoothStatusBars = CreateFrame("StatusBar")
local ssb = SmoothStatusBars

function ssb:Enable()
    self:RegisterEvent("PLAYER_LOGIN")
end

local setValue    
local setThreshold

function ssb:PLAYER_LOGIN()
    self.bars = {}
    self.thresholds = {}
    self.moving = {}
    
    self:CreateHooks()
    
    local index = getmetatable(self).__index
    hooksecurefunc(index, "SetValue", setValue)
    hooksecurefunc(index, "SetMinMaxValues", setThreshold)
    self:SetScript("OnUpdate",self.OnUpdate)
end

function ssb:CreateHooks()
    local bars = self.bars
    local moving = self.moving
    local thresholds = self.thresholds
    
    setValue = function(f, value, override)
        if override then return end
        local previous = bars[f]
        if previous == true or previous == nil then
            bars[f] = value
            return
        end
        if value == previous then
            moving[f] = nil
        else
            local delta = ( value - previous ) / 3
            local threshold = thresholds[f]
            if not threshold then
                setThreshold(f, f:GetMinMaxValues())
                threshold = thresholds[f]
            end
            if delta > threshold or delta < -threshold then
                moving[f] = value
                f:SetValue(previous + delta, true)
                bars[f] = previous + delta
                self:Show()
                return nil
            else
                moving[f] = nil
                bars[f] = value
                return value
            end            
        end
    end
    
    setThreshold = function(f, min, max)
        thresholds[f] = (max - min) * 0.02
    end

end

function ssb:OnUpdate(elapsed)
    local bars = self.bars
    local moving = self.moving
    for bar, destValue in pairs(moving) do
        local set = setValue(bar, destValue)
        if set then bar:SetValue(destValue, true) end        
    end
    if not next(moving) then self:Hide() end -- Stop the OnUpdate when no bars are moving
end

function ssb:OnEvent(event,...)
    local method = self[event]
    if type(method) == "function" then
        method(self,event,...)
    end
end

ssb:SetScript("OnEvent",ssb.OnEvent)
ssb:Enable()